#include "Vector.h" 

Vector::Vector(vector<double>* vec){
      this->vec = *vec;                             
}

Vector::~Vector(){
}

Vector* Vector::vectorByMatrix(Matrix* matrix){
        vector<unsigned int> notNullPos = this->getNotNullPositions();
        vector<double> matrixRow;
        vector< vector<double> > rows;
        vector<double> aux;
        aux.clear();
        rows.clear();
        if (notNullPos.size() > 0)
        {
			for(unsigned int i = 0; i < notNullPos.size(); i++)
			{
				matrixRow.clear();
				matrixRow = matrix->getRow(notNullPos[i]);
				rows.push_back(matrixRow);
			}
			for(unsigned int j = 0; j< rows[0].size(); j++)
			{
				double aux1 = 0;
				for(unsigned int i = 0; i < notNullPos.size(); i++)
				{
					aux1 += this->vec[notNullPos[i]] * rows[i][j];
				}
				aux.push_back(aux1);
			}
        }
        Vector* result = new Vector(&aux);
        return result;
}

Vector* Vector::matrixByVector(Matrix* matrix){
        vector<double> aux;
        vector<double> row;
        aux.clear();
        while (!matrix->wasLast()){
              row.clear();
              matrix->nextRow();
              matrix->getRow(&row);
              if(!matrix->wasLast()){
            	  Vector* vRow = new Vector(&row);
            	  aux.push_back(internalProduct(vRow));
            	  delete vRow;
              }
        }
        Vector* result = new Vector(&aux);
        return result;
}

double Vector::cosine(Vector* vector){
		double divisor = normalize()*vector->normalize();
		if(divisor != 0)
			return internalProduct(vector)/divisor;
		else
			return 0.0;
}

Vector* Vector::matrixCosine(Matrix* matrixT){
        // matrixT ya esta transpuesto
        vector<double> aux;
        vector<double> row;
        aux.clear();
        while (!matrixT->wasLast()){
              row.clear();
              matrixT->nextRow();
              matrixT->getRow(&row);
              if(!matrixT->wasLast()){
				  Vector* vRow = new Vector(&row);
				  aux.push_back(cosine(vRow));
				  delete vRow;
              }
        }
        Vector* result = new Vector(&aux);
        return result;
}

double Vector::internalProduct(Vector* vector){
       double iProduct = 0.0;
       if ((this->vec).size() == vector->size()){
          for (unsigned long i=0; i < this->size(); i++){
              iProduct += this->get(i) * vector->get(i);
          }
       }
       return iProduct;
}

unsigned long Vector::size(){
     return this->vec.size();   
}

double Vector::get(long pos){
       return this->vec[pos];
}

double Vector::normalize(){
       double norm = 0.0;
       for (unsigned long i=0; i < size(); i++){
           norm += pow(get(i),2);
       }
       return sqrt(norm);
}

vector<double> Vector::getVec(){
               return this->vec;
}

vector<unsigned int> Vector::getNotNullPositions(){
	vector<unsigned int> result;
	result.clear();
	for(unsigned int i = 0; i < this->vec.size(); i++)
	{
		if(this->vec[i] != 0)
			result.push_back(i);
	}
	return result;
}
